package com.zodiac.app.szse.d.d0602.d060201;

import com.zodiac.app.szse.Utils;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.Arrays;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

@Slf4j
@Component
public class D060201Downloader {
    private final RestTemplate restTemplate = new RestTemplate();
    private static final String DOWNLOAD_URL_PREFIX = "http://disc.static.szse.cn/download";

    /**
     * 报告下载
     *
     * @param request
     * @return
     */
    @Retryable(value = RetryException.class, maxAttempts = 5, backoff = @Backoff(delay = 1000, multiplier = 2))
    public Request download(Request request) {

        try {
            final D060201Model model = request.getModel();
            final String downloadUrl = DOWNLOAD_URL_PREFIX + model.getReportPath();
            File saveFile = buildSaveFile(request);
            if (saveFile.exists() && model.getDownloadStatus() == D060201Model.DownloadStatus.SUCCESSFUL) {
                return request;
            }

            HttpEntity<Object> entity = new HttpEntity<>(new HttpHeaders());
            byte[] body = restTemplate.exchange(downloadUrl, HttpMethod.GET, entity, byte[].class).getBody();

            // 检查PDF是否有效
            if (null == body || body.length == 0) {
                log.error("下载的PDF为空【{}】", downloadUrl);
                throw new RuntimeException("下载的PDF为空【" + downloadUrl + "】");
            }
            if (!Utils.checkPdfIsValid(Arrays.copyOf(body, body.length))) {
                log.error("下载的PDF无效【{}】大小【{}】KB", downloadUrl, (body.length / 1024));
                throw new RuntimeException("下载的PDF无效【" + downloadUrl + "】");
            }

            if (!saveFile.getParentFile().exists()) {
                saveFile.getParentFile().mkdirs();
            }
            if (!saveFile.exists()) {
                saveFile.createNewFile();
            }
            Files.write(saveFile.toPath(), body);

            request.getModel().setDownloadStatus(D060201Model.DownloadStatus.SUCCESSFUL);
            return request;
        } catch (Exception e) {
            throw new RetryException(e, request);
        }
    }

    @Recover
    protected Request recover(RetryException e) {
        final Request request = e.getRequest();
        request.getModel().setDownloadStatus(D060201Model.DownloadStatus.FAILED);
        return request;
    }

    /**
     * 构建保存路径
     *
     * @param request
     * @return
     */
    private File buildSaveFile(Request request) {
        D060201Model model = request.getModel();
        final String year = model.getReportYear();
        final String month = D060201Extractor.ReportCategory.valueOf(model.getReportCategory()).getMonth();
        final String stockCode = model.getStockCode();
        String[] reportPathItems = model.getReportPath().split("/");
        String reportFileName = reportPathItems[reportPathItems.length - 1];

        return Paths.get(request.getStorePath().getAbsolutePath(), year + month, stockCode, reportFileName).toFile();
    }

    @Builder
    @Data
    public static class Request {
        private File storePath;
        private D060201Model model;
        private String table;
    }

    @Data
    public static class RetryException extends RuntimeException {
        private Request request;

        public RetryException(Request request) {
            this.request = request;
        }

        public RetryException(Throwable cause, Request request) {
            super(cause);
            this.request = request;
        }
    }

}
